using UnityEngine;
using System.IO;
using System.Collections;

public class BM_GameManager : MonoBehaviour
{
	public enum LoadingType
	{
		LOADTYPE_ASYNC
	,	LOADTYPE_SYNC
	}
	
	public enum Scenes
	{
		SCENE_NONE 			 = -1
		
	,	SCENE_ZERO
	, 	SCENE_GAME
		
	,	SCENE_COUNT
	}
	
	public struct SceneData
	{
		public Scenes					m_eSceneId;
		public LoadingType				m_eLoadingType;
		
		public SceneData(Scenes eSceneName, LoadingType eLoadingType)
		{
			m_eSceneId = eSceneName;
			m_eLoadingType = eLoadingType;
		}
	}
	
	public struct SceneTransitionData
	{
		public Scenes		m_eCurrentScene;
		public MessageID	m_eEvent;
		public Scenes		m_eDestinationScene;
		
		public SceneTransitionData(Scenes eCurrentScene, MessageID eEvent, Scenes eDestinationScene)
		{
			m_eCurrentScene = eCurrentScene;
			m_eEvent = eEvent;
			m_eDestinationScene = eDestinationScene;
		}
	}

	
	#region Members
		
	private SceneData[] m_vSceneData =
	{
		new SceneData(Scenes.SCENE_ZERO,			LoadingType.LOADTYPE_SYNC)
//	,	new SceneData(Scenes.SCENE_SPLASHSCREENS,	LoadingType.LOADTYPE_ASYNC)
//	,	new SceneData(Scenes.SCENE_MAINMENU,		LoadingType.LOADTYPE_ASYNC)
	,	new SceneData(Scenes.SCENE_GAME,			LoadingType.LOADTYPE_SYNC)
	};
	
	private SceneTransitionData[] m_vTransitionTable =
	{
		new SceneTransitionData(Scenes.SCENE_GAME,							MessageID.MSGID_NONE, 						Scenes.SCENE_NONE)
	};
	
	
	// public 
	public Scenes				m_eStartScene 	= Scenes.SCENE_GAME;
	
	
	private bool				m_bInitialized = false;
	
	private bool				m_bOnSystemPause = false;
	private bool				m_b_Received_OnFocus_False_After_OnPause_False = false;
	
	private AsyncOperation		m_asyncOperation 	= null;
	private BM_MessageHandler	m_rMessageHandler 	= null;
//	private SV_LoadingScreen	m_rLoadingScreen 	= null;
	
	private MessageID			m_eLastMessage = MessageID.MSGID_NONE;
	private Scenes				m_eCurrentScene = Scenes.SCENE_ZERO;
	
	
	#endregion
	
	
	#region Properties
	
	public BM_MessageHandler MessageHandler
	{
		get { return m_rMessageHandler; }
	}
	
	public MessageID LastMessage
	{
		get { return m_eLastMessage; }
	}
	
	#endregion
	
	
	public void Awake()
	{
		m_rManagerReference = this;
		Application.targetFrameRate = 2000;
		
		// inizializzo le variabili relative alla risoluzione e aspectratio
		BM_Utils.InitializeScreenStuff();
		
		
		// aggiungo i vari manager al gameobject
		gameObject.AddComponent<BM_MessageManager>();
		gameObject.AddComponent<BM_AudioManager>();
		gameObject.AddComponent<BM_InputManager>();
		gameObject.AddComponent<BM_TextureManager>();
		gameObject.AddComponent<BM_AppDataManager>();

//		
//		gameObject.AddComponent<SV_PluginsManager>();
//		gameObject.AddComponent<SV_FontManager>();
		
		// carico tutti i texture atlas
//		SV_TextureManager.Instance().LoadTexture(TextureId.TEXTUREID_MEGATEXTURE_UI);
//		SV_TextureManager.Instance().LoadTexture(TextureId.TEXTUREID_MEGATEXTURE_GAME);
		
		m_rMessageHandler = new BM_MessageHandler();
		
		// lo schermo non deve mai andare in risparmio energetico
		Screen.sleepTimeout = SleepTimeout.NeverSleep;
		
		m_bInitialized = true;
	}
	
	public void Start()
	{	
		m_eLastMessage = MessageID.MSGID_NONE;
	
		m_eCurrentScene =  Scenes.SCENE_ZERO;
		
		BM_InputManager.Instance().SetTouchEmulationInputDevice(BM_InputManager.PlatformFamily.INPUT_TOUCH, true);
		BM_InputManager.Instance().SetTouchEmulationInputDevice(BM_InputManager.PlatformFamily.INPUT_MOUSE, true);
		
		LoadScene(m_eStartScene);
		
		Object.DontDestroyOnLoad(gameObject);
	}
	
	public void OnDestroy()
	{
		// reimposto i setting di sistema
		Screen.sleepTimeout = SleepTimeout.SystemSetting;
		
		m_rMessageHandler.RemoveFromDispatcher();
		
		
		// scarico tutti i texture atlas
//		SV_TextureManager.Instance().UnloadTexture(TextureId.TEXTUREID_MEGATEXTURE_UI);
//		SV_TextureManager.Instance().UnloadTexture(TextureId.TEXTUREID_MEGATEXTURE_GAME);
		
		m_rManagerReference = null;
	}	
	
	// OnApplicationPause e OnApplicationFocus sono necessari per ripristinare lo stato dell'audio al rientro nell'applicazione
	// su alcuni sistemi (Android) il SO non garantisce l'ordine con cui vengono chiamate queste callback
	// per tale ragione solo l'ultima callback invocata potrà ristabilire lo stato dell'audio.
	
	public void OnApplicationPause(bool bPause)
	{
		if(bPause)
		{
			if(m_bInitialized)
			{
				BM_AudioManager.Instance().DisableAudioStatus();
//				SV_AppDataManager.Instance().OnPause();
			}
			
			m_bOnSystemPause = true;
		}
		else
		{
			if(!m_b_Received_OnFocus_False_After_OnPause_False && m_bInitialized)
			{
				BM_AudioManager.Instance().RestoreAudioStatus();
//				SV_PluginsManager.Instance().OnResume();
			}
			
			m_b_Received_OnFocus_False_After_OnPause_False = false;
			m_bOnSystemPause = false;
		}
	}
	
	public void OnApplicationFocus(bool bFocus)
	{
		if(!bFocus)
		{
			if(m_bOnSystemPause)
				m_b_Received_OnFocus_False_After_OnPause_False = true;
		}
		else if(m_bInitialized)
		{
			BM_AudioManager.Instance().RestoreAudioStatus();
//			SV_PluginsManager.Instance().OnResume();
		}
	}
	
	public void Update()
	{
#if UNITY_EDITOR
		if(Input.GetKeyDown(KeyCode.Backspace))
			PlayerPrefs.DeleteAll();
#endif
		
		if(m_asyncOperation != null)
//		{
//			if(m_asyncOperation.progress >= 1.0f)
//			{
////				m_rLoadingScreen.enabled = false;
////				m_rLoadingScreen.LoadingOperation = m_asyncOperation = null;
//			}
//			else if(!m_rLoadingScreen.enabled)
//			{
////				m_rLoadingScreen.LoadingOperation = m_asyncOperation;
////				m_rLoadingScreen.enabled = true;
//			}
//		}
		
 		if(m_rMessageHandler.HasMessages)
		{
			for(int iMapRow = 0; iMapRow < m_vTransitionTable.Length; ++iMapRow)
			{
				if( m_vTransitionTable[iMapRow].m_eCurrentScene == m_eCurrentScene && 
					m_rMessageHandler.ReceivedMessageWithID(m_vTransitionTable[iMapRow].m_eEvent) != null )
				{
					m_eLastMessage = m_vTransitionTable[iMapRow].m_eEvent;
					LoadScene(m_vTransitionTable[iMapRow].m_eDestinationScene);
					break;
				}
			}
		}
	}
	
	private string GetSceneName(Scenes eScene)
	{
		string strRVal = "";
		
		if(eScene != Scenes.SCENE_NONE && m_vSceneData[(int)eScene].m_eSceneId == eScene)
		{
			strRVal = eScene.ToString().ToLower();
		}
		else if(Debug.isDebugBuild)
		{
			Debug.LogError("GP_GameManager.GetSceneName: attenzione! non riesco a trovare il nome della scena!");
			Debug.DebugBreak();
		}

		return strRVal;
	}
	
	private void LoadScene(Scenes eNextScene)
	{
		if(eNextScene != Scenes.SCENE_NONE)
		{
//			if(eNextScene == Scenes.SCENE_BEGINWORLD && CM_AppDataManager.Instance().CurrentLevel > 0)
//				eNextScene = Scenes.SCENE_LEVEL;
			
			if(m_vSceneData[(int)eNextScene].m_eLoadingType == LoadingType.LOADTYPE_SYNC)
			{
				Application.LoadLevel(GetSceneName(eNextScene));
				m_asyncOperation = null;
			}
			else if(m_vSceneData[(int)eNextScene].m_eLoadingType == LoadingType.LOADTYPE_ASYNC)
				m_asyncOperation = Application.LoadLevelAsync(GetSceneName(eNextScene));
		
			Time.timeScale = 1.0f; // per sicurezza...
			m_eCurrentScene = eNextScene;
		}
	}
	
	#region Functions
	
	#endregion
	
	
	#region Singleton
	
	private static BM_GameManager		m_rManagerReference = null;
	
	public static BM_GameManager Instance()
	{
		if(m_rManagerReference == null)
		{
			Debug.LogError("BM_GameManager.Instance() -> Manager non inizializzato! ERRORE!");
			Debug.DebugBreak();
		}
		
		return m_rManagerReference;
	}
	
	#endregion
}
